#pragma once
#include <iostream>
#include <pthread.h>
#include <functional>
#include <string>
#include <cassert>
#include <cstdio>
#include <atomic>
class Thread;
class ThreadData
{
public:
    Thread* _thread;
    void* _args;
    ThreadData(Thread* thread, void* args)
        :_thread(thread), _args(args)
    {}
};
class Thread
{
private:
    using func_t = std::function<void*(void*)>;
    Thread(const Thread&) = delete;
    Thread& operator=(const Thread&) = delete;
public:
    Thread()
    {
        char buffer[64];
        snprintf(buffer, sizeof buffer, "thread %d", _num.load());
        _num++;
        _name = buffer;
    }

    static void* start_toutine(void* args)
    {
        ThreadData* threadData = static_cast<ThreadData*>(args);
        Thread* _this = threadData->_thread;
        void* ags = threadData->_args;
        delete threadData;
        return _this->_callBack(ags);
    }

    void start(func_t func, void* args)
    {
        _callBack = func;
        _args = args;
        ThreadData* threadData = new ThreadData(this, _args);
        int n = pthread_create(&_id, nullptr, start_toutine, threadData);
        assert(0 == n);      
        (void)n;
    }

    std::string thread_name()
    {
        return _name;
    }
    
    void join()
    {
        int n = pthread_join(_id, nullptr);
        assert(0 == n);
    }
private:
    std::string _name; //线程名
    pthread_t _id; //线程id
    func_t _callBack; //回调函数
    void* _args; //参数
    static std::atomic<int> _num; //用来推导线程名的计数器
};

std::atomic<int> Thread::_num(1);